#include <iostream>
#include "../aed2/aed2.h"
#include "../src/multconjAcotado.h"
#include "../aed2/ConjAcotado.h"
#include "test.h"
using namespace std;

void testCreacion(ostream& os) {
	std::cerr << "Test Creacion" << std::endl;
	MultConjAcotado mca(10);		// Crea un conjunto vacio con cota 10
	AFIRMAR(mca.Cardinal() == 0);
	ASEGURAR(mca, "{}");
	for (aed2::Nat i = 0; i < 10; i++){
		NEGAR(mca.Pertenece(i));
	}
	NEGAR(mca.Pertenece(10));
}

void testAgregar(ostream& os) {
	std::cerr << "Test Agregar" << std::endl;
	MultConjAcotado mca(10);
	mca.Agregar(5, 1);				// Agrega un elemento nuevo por debajo de la cota 10
	AFIRMAR(mca.Cardinal() == 1);
	AFIRMAR(mca.Pertenece(5));
	AFIRMAR(mca.Cardinal(5) == 1);
	AFIRMAR(mca.Cardinal(4) == 0);
	ASEGURAR(mca, "{5}");
	
	mca.Agregar(9,2);
	mca.Agregar(9,3);
	AFIRMAR(mca.Cardinal() == 6);
	AFIRMAR(mca.Pertenece(9));
	AFIRMAR(mca.Cardinal(9) == 5);
	AFIRMAR(mca.Cardinal(4) == 0);
	ASEGURAR(mca, "{5,9,9,9,9,9}");
	
	MultConjAcotado mcb(30);
	mcb.Agregar(11, 2);
	AFIRMAR(mcb.Cardinal()== 2);
	AFIRMAR(mcb.Pertenece(11));
	AFIRMAR(mcb.Cardinal(11) == 2);
	AFIRMAR(mcb.Cardinal(4) == 0);
	ASEGURAR(mcb, "{11,11}");
	
}

void testMinimoQuitar(ostream& os) {
	std::cerr << "Test Minimo y Quitar" << std::endl;
	MultConjAcotado mca(10);
	mca.Agregar(4, 3);
	AFIRMAR(mca.Minimo() == 4);	// Pide el mínimo
	ASEGURAR(mca, "{4,4,4}");
	
	mca.Agregar(5, 2);
	AFIRMAR(mca.Minimo() == 5);	// Pide el mínimo
	ASEGURAR(mca, "{5,5,4,4,4}");
	
	mca.Quitar(4, 2);
	AFIRMAR(mca.Cardinal() == 3);
	AFIRMAR(mca.Pertenece(4));
	AFIRMAR(mca.Cardinal(4) == 1);
	AFIRMAR(mca.Minimo() == 4);	// Pide el mínimo
	ASEGURAR(mca, "{4,5,5}");
	
	mca.Quitar(4, 10); 				// Quita el último 4, pide quitar 10, pero en realidad sólo quita los que hubieran
	AFIRMAR(mca.Cardinal() == 2);
	NEGAR(mca.Pertenece(4));
	AFIRMAR(mca.Cardinal(4) == 0);
	AFIRMAR(mca.Minimo() == 5);	// Pide el mínimo
	ASEGURAR(mca, "{5,5}");
}

void testPertenece(ostream& os) {
	std::cerr << "Test Pertenece" << std::endl;
	MultConjAcotado mca(10);
	mca.Agregar(5, 1);
	AFIRMAR(mca.Pertenece(5));	// Verifica que un elemento pertenece
	NEGAR(mca.Pertenece(7));		// Verifica que un elemento no pertenece
	NEGAR(mca.Pertenece(11));	// Verifica que un elemento fuera de rango no pertenece

	mca.Agregar(5, 1);
	AFIRMAR(mca.Pertenece(5));	// Verifica que un elemento pertenece
	ASEGURAR(mca, "{5,5}");
	mca.Quitar(5, 2);
	ASEGURAR(mca, "{}");
	NEGAR(mca.Pertenece(5));		// Verifica que un elemento fuera de rango no pertenece
	NEGAR(mca.Pertenece(7));		// Verifica que un elemento fuera de rango no pertenece
}

void testCardinal(ostream& os) {
	std::cerr << "Test Cardinal" << std::endl;
	MultConjAcotado mca(10);
	mca.Agregar(5, 1);
	AFIRMAR(mca.Cardinal() == 1);	// Pide el cardinal de un conjunto con un elemento
	
	mca.Agregar(5, 2);
	AFIRMAR(mca.Cardinal() == 3);	// Pide el cardinal de un conjunto con tres elementos
	
	mca.Quitar(5, 2);
	AFIRMAR(mca.Cardinal() == 1);	// Pide el cardinal de un conjunto con un elemento
	mca.Agregar(8, 1000);
	AFIRMAR(mca.Cardinal() == 1001); // Pide el cardinal de un conjunto con 1001 elementos
	
	mca.Quitar(5, 1);
	AFIRMAR(mca.Cardinal() == 1000); // Pide el cardinal de un conjunto con 1000 elementos
	
	MultConjAcotado mcb(30);
	AFIRMAR(mcb.Cardinal() == 0); // Pide el cardinal de un conjunto vacio
}

void testConj(ostream& os){ //testea el iterador con el conj de elementos distintos
	std::cerr << "Test Conj" << std::endl;
	MultConjAcotado mca(30);
	mca.Agregar(5, 10);
	//std::cerr << mca << std::endl;
	mca.Agregar(8, 100);
	//std::cerr << mca << std::endl;
	AFIRMAR(mca.CantDistintos() == 2);
	mca.Agregar(28, 10);
	//std::cerr << mca << std::endl;
	mca.Quitar(8, 90);
	//std::cerr << mca << std::endl;
	AFIRMAR(mca.CantDistintos() == 3);
	mca.Quitar(8,10);
	NEGAR(mca.Pertenece(8));
	AFIRMAR(mca.CantDistintos() == 2);
	//std::cerr << mca << std::endl;
	ASEGURAR(mca, "{5,5,5,5,5,5,5,5,5,5,28,28,28,28,28,28,28,28,28,28}");

	MultConjAcotado::const_Iterador_Unicos it = mca.Conj();
	AFIRMAR(it.HaySiguiente());
	AFIRMAR(it.Siguiente() == 5);
	it.Avanzar();
	AFIRMAR(it.HaySiguiente());
	AFIRMAR(it.Siguiente() == 28);
	it.Avanzar();
	NEGAR(it.HaySiguiente());
}


void testIterador(ostream& os){

	std::cerr << "Test Iterador" << std::endl;

	MultConjAcotado mca(101);
	mca.Agregar(5, 514);
	mca.Agregar(8, 1);
	mca.Agregar(100, 99);

	MultConjAcotado::const_Iterador it = mca.CrearIt();
	AFIRMAR(it.HaySiguiente());
	ASEGURAR(it.Siguiente(), 8);
	ASEGURAR(it.CardinalSiguiente(), 1);
	it.Avanzar();
	AFIRMAR(it.HaySiguiente());
	ASEGURAR(it.Siguiente(), 5);
	ASEGURAR(it.CardinalSiguiente(), 514);
	it.Retroceder();
	AFIRMAR(it.HaySiguiente());
	ASEGURAR(it.Siguiente(), 8);
	ASEGURAR(it.CardinalSiguiente(), 1);
	it.Avanzar();
	AFIRMAR(it.HaySiguiente());
	ASEGURAR(it.Siguiente(), 5);
	ASEGURAR(it.CardinalSiguiente(), 514);
	it.Avanzar();
	AFIRMAR(it.HaySiguiente());
	ASEGURAR(it.Siguiente(), 100);
	ASEGURAR(it.CardinalSiguiente(), 99);
	it.Avanzar();
	NEGAR(it.HaySiguiente());
}

int main() {
    
    Tester::Instance()->NuevoSet("MultiConjuntoAcotado");
    Tester::Instance()->UsarSet("MultiConjuntoAcotado");
    
    Tester::Instance()->Declarar("Creacion", &testCreacion);
    Tester::Instance()->Declarar("Agregar", &testAgregar);
    Tester::Instance()->Declarar("MinimoQuitar", &testMinimoQuitar);
    Tester::Instance()->Declarar("Pertence", &testPertenece);
    Tester::Instance()->Declarar("Cardinal", &testCardinal);
    Tester::Instance()->Declarar("Conj", &testConj);
    Tester::Instance()->Declarar("Iterador", &testIterador);
    
    Tester::Instance()->setVerborragia(1);
    Tester::Instance()->Ejecutar("MultiConjuntoAcotado");
    
    return 0;
}

